home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-03-29 | 18.2 KB | 624 lines | [TEXT/MPS ] |
- {
- Written by Chris Thorman. Based on an example by Jay Hodgdon.
- Copyright 1990 Apple Computer, Inc.
-
- Permission granted for any kind of use as long as this notice is retained.
-
- Apple makes no claims as to the correctness or value of this software for
- any purpose. In fact, this software may well have bugs which will crash
- your machine at crucial moments.
- }
-
- {$R-}
- {$S ProgressWindoid }
-
- {
- ProgressWindoid (WindowName, Loc, [Width, Text, Fraction, TextFont, TextSize])
-
- This HyperCard external window command creates a windoid that can be used
- to show progress of a lengthy operation.
-
- The XFCN is called once and if successful, leaves an XWindoid which
- HyperCard will subsequently manage. A successful call is indicated
- by an empty return value from the XFCN. If the return value is not
- empty, then it should be interpreted as an error message.
-
- All interaction with the window takes place by getting and setting
- its properties (see below), and through HyperCard’s open, close, show,
- and hide commands.
-
- The WindowName argument is the name that the window will be given. It
- is required. After creating the window, this name will be used from
- HyperTalk to refer to it.
-
- The Loc argument is the point that will become the upper-left corner
- of the windoid. It is a two-item string in the form “20,50”. It is
- a card-relative number, not screen relative. It is required.
-
- The optional Width argument is total width of the windoid in pixels. The
- minimum width is 140 pixels. The maximum is 1200 pixels. The default
- is 250 pixels.
-
- The optional Text argument is the text that appears above the
- progress bar in the windoid. It may be empty. It defaults to “Progress:”.
-
- The optional Fraction argument is the Fraction that the XWindoid
- starts with when it is created. It is a floating point number between
- 0.0 and 1.0. It defaults to 0.0.
-
- The optional TextFont argument is the font that will be used for the text
- in the windoid. The name of the font (e.g. “Helvetica”) is used to specify
- the font. The default font is whatever font corresponds to 0 on the current
- system (usually Geneva).
-
- The optional TextSize argument is the size of the text in the window. It
- is 12 by default. The minimum size is 1 point and the maximum size is 127
- points.
-
- All of the optional arguments correspond to HyperCard properties of the
- windoid. These are: the width, the text, the fraction, the textFont, and
- the textSize.
-
- In addition to these special properties, the windoid also supports
- HyperCard’s standard window properties: the loc, the visible, and the
- properties (which returns a list of the special properties of the windoid).
-
- }
-
- UNIT DummyUnit;
-
- INTERFACE
-
- USES
- { Traps, Desk, OSUtils, }
- Files, ToolUtils, Memory, Windows, SANE, Fonts,
- Types, Events, TextEdit, Menus, HyperXCmd;
-
- PROCEDURE EntryPoint(paramPtr: XCmdPtr);
-
- IMPLEMENTATION
-
- PROCEDURE ProgressWindoid (paramPtr: XCmdPtr);
- FORWARD;
-
- PROCEDURE EntryPoint(paramPtr: XCmdPtr);
- BEGIN
- ProgressWindoid (paramPtr)
- END { entrypoint } ;
-
-
- PROCEDURE ProgressWindoid (paramPtr: XCmdPtr);
-
- CONST
-
- MinParams = 2;
- MaxParams = 7;
-
- TextTopSpace = 5;
- TextBottomSpace = 5;
-
- TextLeftSideSpace = 20;
-
-
- { ProgBarTop } { = TextTopSpace + TextSize + TextBottomSpace}
- ProgBarSideSpace = 20;
-
- { ProgBarWidth } { = WindowWidth - (2 * ProgBarSideSpace) }
- ProgBarHeight = 20;
- ProgBarBottomSpace = 10;
-
-
- { WindowWidth } { Determined by user }
- { WindowHeight } { = ProgBarTop + ProgBarHeight + ProgBarBottomSpace }
-
-
- TYPE
-
- ParamArray = PACKED ARRAY [1..MaxParams] OF Str255;
-
- ProgressWindoidInfoRecord = RECORD
- WindowText: Str255;
- WindowFraction: Extended;
- ProgBarTop: Integer; { Cached here, but could be determined from txSize }
- ProgBarWidth: Integer; { Cached here, but could be determined from portRect }
- END;
-
- ProgressWindoidInfoPtr = ^ProgressWindoidInfoRecord;
- ProgressWindoidInfoHandle = ^ProgressWindoidInfoPtr;
-
- VAR
- TheResult: Handle;
-
- ParamStrings: ParamArray;
-
- WindowNameParam: Str255;
- LocParam: Point;
- WidthParam: Integer;
- TextParam: Str255;
- FractionParam: Extended;
- TextFontParam: Integer;
- TextSizeParam: Integer;
-
- WindowBounds: Rect;
- MyWindowPtr: WindowPtr;
-
- ProgWindInfo: ProgressWindoidInfoHandle;
-
- PROCEDURE ExitWithHandle(aHandle: Handle);
- BEGIN
- ZeroTermHandle(paramPtr, aHandle);
- WITH paramPtr^ DO BEGIN
- returnValue := aHandle;
- EXIT(ProgressWindoid);
- END;
- END;
-
- PROCEDURE ExitWithMessage(aString: Str255);
- BEGIN
- WITH paramPtr^ DO BEGIN
- returnValue := PasToZero(paramPtr, aString);
- EXIT(ProgressWindoid);
- END;
- END;
-
- PROCEDURE ExitWithError(aString: Str255);
- BEGIN
- ExitWithMessage(concat('•••••••• Error: ', aString, '.'));
- END;
-
- PROCEDURE LimitFractionValue(VAR Fraction: Extended);
- BEGIN
- IF (ClassExtended(Fraction) <> NormalNum) THEN Fraction := 0.0;
- IF (Fraction < 0.0) THEN Fraction := 0.0;
- IF (Fraction > 1.0) THEN Fraction := 1.0;
- END;
-
- PROCEDURE LimitWidthValue(VAR WindWidth: Integer);
- BEGIN
- IF (WindWidth < 140) THEN WindWidth := 140;
- IF (WindWidth > 1200) THEN WindWidth := 1200;
- END;
-
- PROCEDURE LimitTextSizeValue(VAR TextSize: Integer);
- BEGIN
- IF (TextSize < 1) THEN TextSize := 12;
- IF (TextSize > 127) THEN TextSize := 12;
- END;
-
- PROCEDURE ParseParams;
- VAR
- ParamNum: integer;
- BEGIN
- WITH paramPtr^ DO BEGIN
- IF (paramCount < MinParams) THEN ExitWithError('Too few parameters');
- IF (paramCount > MaxParams) THEN ExitWithError('Too many parameters');
-
- ParamNum := 1; {* Required *}
-
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- WindowNameParam := ParamStrings[ParamNum];
- IF (WindowNameParam = '') THEN ExitWithError('Empty window name was given');
-
- ParamNum := 2; {* Required *}
-
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- StrToPoint(paramPtr, ParamStrings[ParamNum], LocParam);
-
- { LocParam is passed in as card-relative, but we will need absolute
- coordinates. }
- { As it happens, LocalToGlobal accomplishes this, but the more correct
- way would probably be to use EvalExpr(paramPtr, 'the loc of card window')
- and add that loc to the loc that was passed in. }
-
- LocalToGlobal(LocParam);
-
- ParamNum := 3; {* Optional *}
-
- IF (paramCount >= ParamNum) THEN
- BEGIN
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- WidthParam := StrToNum(paramPtr, ParamStrings[ParamNum]);
- LimitWidthValue(WidthParam);
- END
- ELSE
- BEGIN
- WidthParam := 250;
- END;
-
- ParamNum := 4; {* Optional *}
-
- IF (paramCount >= ParamNum) THEN
- BEGIN
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- TextParam := ParamStrings[ParamNum];
- END
- ELSE
- BEGIN
- TextParam := 'Progress:';
- END;
-
- ParamNum := 5; {* Optional *}
-
- IF (paramCount >= ParamNum) THEN
- BEGIN
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- IF (ParamStrings[ParamNum] = '') THEN FractionParam := 0.0
- ELSE FractionParam := StrToExt(paramPtr, ParamStrings[ParamNum]);
- LimitFractionValue(FractionParam);
- END
- ELSE
- BEGIN
- FractionParam := 0.0;
- END;
-
- ParamNum := 6; {* Optional *}
-
- IF (paramCount >= ParamNum) THEN
- BEGIN
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- GetFNum(ParamStrings[ParamNum], TextFontParam);
- END
- ELSE
- BEGIN
- TextFontParam := 0;
- END;
-
- ParamNum := 7; {* Optional *}
-
- IF (paramCount >= ParamNum) THEN
- BEGIN
- ZeroToPas(paramPtr, params[ParamNum]^, ParamStrings[ParamNum]);
- TextSizeParam := StrToNum(paramPtr, ParamStrings[ParamNum]);
- LimitTextSizeValue(TextSizeParam);
- END
- ELSE
- BEGIN
- TextSizeParam := 12;
- END;
-
- END;
-
- END; { ParseParams }
-
- PROCEDURE DoSetup;
- VAR
- ProgBarTop: Integer;
- ProgBarWidth: Integer;
- WindowHeight: Integer;
- BEGIN
- { Put values into the parameter variables or fail trying. }
- ParseParams;
-
- ProgBarTop := TextTopSpace + TextSizeParam + TextBottomSpace;
- ProgBarWidth := WidthParam - (2 * ProgBarSideSpace);
-
- WindowHeight := ProgBarTop + ProgBarHeight + ProgBarBottomSpace;
-
- WindowBounds.Left := LocParam.h;
- WindowBounds.Top := LocParam.v;
- WindowBounds.Right := LocParam.h + WidthParam;
- WindowBounds.Bottom := LocParam.v + WindowHeight;
-
- ProgWindInfo := ProgressWindoidInfoHandle(NewHandle(Sizeof(ProgressWindoidInfoRecord)));
- IF (ProgWindInfo = NIL) THEN ExitWithError('Couldn’t allocate storage for window variables');
-
- MyWindowPtr := NewXWindow(paramPtr, WindowBounds, WindowNameParam, FALSE,
- palNoGrowProc, FALSE, TRUE);
-
- IF (MyWindowPtr = NIL) THEN
- BEGIN
- DisposHandle(Handle(ProgWindInfo));
- ExitWithError('Couldn’t create XWindow');
- END;
-
- MyWindowPtr^.txFont := TextFontParam;
- MyWindowPtr^.txSize := TextSizeParam;
-
- { All of the XWindow’s variables must be stored in a handle to a
- record (of type ProgressWindoidInfoRecord whose fields are declared at the top) and then
- this handle is stored in the WRefCon of the window once it is created.
- This way they can be accessed again when the window receives messages.
- The handle is destroyed when the window gets its goodbye kiss.
- }
-
- ProgWindInfo^^.WindowText := TextParam;
- ProgWindInfo^^.WindowFraction := FractionParam;
- ProgWindInfo^^.ProgBarTop := ProgBarTop;
- ProgWindInfo^^.ProgBarWidth := ProgBarWidth;
-
- SetWRefCon(MyWindowPtr, LONGINT(ProgWindInfo));
-
- END;
-
- PROCEDURE KillXWindow(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr);
- { dispose of the window's data structures }
- BEGIN
-
- { None of the fields in the XWindowInfoRec need to be destroyed,
- just the handle itself. }
- DisposHandle(Handle(ProgWindInfo));
- END;
-
-
- PROCEDURE DrawText(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr);
- VAR
- TextRect: Rect;
- FInfo: FontInfo;
- WindowWidth: Integer;
- BEGIN
- GetFontInfo(FInfo);
-
- WindowWidth := TheWindow^.portRect.Right - TheWindow^.portRect.Left;
-
- SetRect(TextRect, TextLeftSideSpace, TextTopSpace,
- WindowWidth, TextTopSpace + FInfo.ascent + FInfo.descent);
- EraseRect(TextRect);
-
- MoveTo(TextLeftSideSpace,TextTopSpace + FInfo.ascent);
- DrawString(ProgWindInfo^^.WindowText);
- END;
-
- PROCEDURE DrawProgBar(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr);
- VAR
- ProgressBar: Rect;
- CompletionBar: Rect;
- UnCompleteBar: Rect;
- BEGIN
-
- SetRect(ProgressBar, ProgBarSideSpace, ProgWindInfo^^.ProgBarTop,
- ProgBarSideSpace + ProgWindInfo^^.ProgBarWidth,
- ProgWindInfo^^.ProgBarTop + ProgBarHeight);
-
- SetRect(CompletionBar,
- ProgressBar.Left + 1,
- ProgressBar.Top + 1,
- ProgressBar.Left + 1 + Num2Integer((ProgWindInfo^^.ProgBarWidth - 1) * ProgWindInfo^^.WindowFraction),
- ProgressBar.Bottom - 1);
-
- SetRect(UnCompleteBar, CompletionBar.Right, CompletionBar.Top,
- ProgBarSideSpace + ProgWindInfo^^.ProgBarWidth - 1,
- CompletionBar.Bottom);
-
- PaintRect(CompletionBar);
- EraseRect(UncompleteBar);
- FrameRect(ProgressBar);
-
- END;
-
- PROCEDURE DoUpdate(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr);
- VAR
- WindowRect: Rect;
- BEGIN
- WindowRect := theWindow^.portRect;
-
- BeginUpdate(theWindow);
-
- EraseRect(WindowRect);
- DrawText(ProgWindInfo, theWindow);
- DrawProgBar(ProgWindInfo, theWindow);
-
- EndUpdate(theWindow);
- END;
-
-
- PROCEDURE DoMouseDown(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr; theEvent: EventRecord);
- BEGIN
- CASE FindWindow(theEvent.where,theWindow) OF
- inGoAway:
- IF TrackGoAway(theWindow,theEvent.where) THEN
- CloseXWindow(paramPtr,theWindow);
-
- inDrag: paramPtr^.passFlag:= TRUE;
-
- { inContent: NOTHING }
-
- END; {case}
- END;
-
- FUNCTION GetProperty(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr; propName: StringPtr): Handle;
- {The procedure causes the window to respond to a }
- {get the myValue of window "TestWindow" }
- VAR
- TempString: Str255;
- BEGIN
- IF StringEqual(paramPtr,propName^,'Properties') {List of all other properties}
- THEN
- BEGIN
- GetProperty := PasToZero(paramPtr, 'Text,Fraction,Width,TextFont,TextSize');
- Exit(GetProperty);
- END;
-
- IF StringEqual(paramPtr,propName^,'Width')
- THEN
- BEGIN
- NumToStr(paramPtr, TheWindow^.portRect.Right - TheWindow^.portRect.Left, TempString);
- GetProperty := PasToZero(paramPtr, TempString);
- Exit(GetProperty);
- END;
-
- IF StringEqual(paramPtr,propName^,'Text')
- THEN
- BEGIN
- GetProperty := PasToZero(paramPtr, ProgWindInfo^^.WindowText);
- Exit(GetProperty);
- END;
-
- IF StringEqual(paramPtr,propName^,'Fraction')
- THEN
- BEGIN
- ExtToStr(paramPtr, ProgWindInfo^^.WindowFraction, TempString);
- GetProperty := PasToZero(paramPtr, TempString);
- Exit(GetProperty);
- END;
-
- IF StringEqual(paramPtr,propName^,'TextFont')
- THEN
- BEGIN
- GetFontName(TheWindow^.txFont, TempString);
- GetProperty := PasToZero(paramPtr, TempString);
- Exit(GetProperty);
- END;
-
- IF StringEqual(paramPtr,propName^,'TextSize')
- THEN
- BEGIN
- NumToStr(paramPtr, TheWindow^.txSize, TempString);
- GetProperty := PasToZero(paramPtr, TempString);
- Exit(GetProperty);
- END;
-
- { This handles the properties: loc, visible (HyperCard supplies them) }
- GetProperty:= NIL;
- paramPtr^.passFlag:= TRUE;
- END;
-
- PROCEDURE SetProperty(ProgWindInfo: ProgressWindoidInfoHandle; theWindow: WindowPtr; propName: StringPtr; propVal: Handle);
- {The procedure causes the window to respond to a }
- {"set the yourValue of window "TestWindow" to something" }
- VAR
- TempString: Str255;
-
- NewWidth: Integer;
- WindowHeight: Integer;
-
- NewFontNumber: Integer;
-
- NewSize: Integer;
- ProgBarTop: Integer;
- ProgBarWidth: Integer;
- NewHeight: Integer;
- WindowWidth: Integer;
- BEGIN
- IF StringEqual(paramPtr,propName^,'Fraction')
- THEN
- BEGIN
- ZeroToPas(paramPtr, propVal^, TempString);
- ProgWindInfo^^.WindowFraction := StrToExt(paramPtr, TempString);
- LimitFractionValue(ProgWindInfo^^.WindowFraction);
- DrawProgBar(ProgWindInfo, theWindow);
- END
-
- ELSE IF StringEqual(paramPtr,propName^,'Text')
- THEN
- BEGIN
- ZeroToPas(paramPtr, propVal^, TempString);
- ProgWindInfo^^.WindowText := TempString;
- DrawText(ProgWindInfo, theWindow);
- { Sometimes the font misbehaves & draws in the progbar area }
- DrawProgBar(ProgWindInfo, theWindow);
- END
-
- ELSE IF StringEqual(paramPtr,propName^,'Width')
- THEN
- BEGIN
- ZeroToPas(paramPtr, propVal^, TempString);
- NewWidth := StrToNum(paramPtr, TempString);
- LimitWidthValue(NewWidth);
- ProgWindInfo^^.ProgBarWidth := NewWidth - (2 * ProgBarSideSpace);
-
- WindowHeight := theWindow^.portRect.Bottom - theWindow^.portRect.Top;
- SizeWindow(TheWindow, NewWidth, WindowHeight, TRUE); { forces an update event, maybe }
- InvalRect(theWindow^.portRect);
-
- DrawText(ProgWindInfo, theWindow); { More or less text may fit now. }
- DrawProgBar(ProgWindInfo, theWindow); { The progress bar will be longer or shorter now. }
- END
-
- ELSE IF StringEqual(paramPtr,propName^,'TextFont')
- THEN
- BEGIN
- ZeroToPas(paramPtr, propVal^, TempString);
- GetFNum(TempString, NewFontNumber);
- TheWindow^.txFont := NewFontNumber; { Same as QuickDraw SetFont }
-
- DrawText(ProgWindInfo, theWindow); { More or less text may fit now, but height is the same. }
- { Sometimes the font misbehaves & draws in the progbar area }
- DrawProgBar(ProgWindInfo, theWindow);
- END
-
- ELSE IF StringEqual(paramPtr,propName^,'TextSize')
- THEN
- BEGIN
- ZeroToPas(paramPtr, propVal^, TempString);
- NewSize := StrToNum(paramPtr, TempString);
- LimitTextSizeValue(NewSize);
-
- TheWindow^.txSize := NewSize;
-
- ProgBarTop := TextTopSpace + NewSize + TextBottomSpace;
- ProgWindInfo^^.ProgBarTop := ProgBarTop;
-
- NewHeight := ProgBarTop + ProgBarHeight + ProgBarBottomSpace;
- WindowWidth := theWindow^.portRect.Right - theWindow^.portRect.Left;
- SizeWindow(TheWindow, WindowWidth, NewHeight, TRUE); { forces an update event, maybe }
- InvalRect(theWindow^.portRect);
-
- DrawText(ProgWindInfo, theWindow); { More or less text may fit now. }
- DrawProgBar(ProgWindInfo, theWindow); { The progress bar will be at a different height now. }
- END
-
- ELSE
- BEGIN { This handles the properties: loc, visible (HyperCard supplies them) }
- paramPtr^.passFlag:= TRUE;
- END;
- END;
-
- PROCEDURE ProcessEvent(myXWEventInfoPtr: XWEventInfoPtr; myWindow: WindowPtr; myEvent: EventRecord);
- VAR
- ProgWindInfo: ProgressWindoidInfoHandle;
- BEGIN
- ProgWindInfo := ProgressWindoidInfoHandle(GetWRefCon(myWindow));
-
- CASE myEvent.what OF
- mouseDown: DoMouseDown(ProgWindInfo, myWindow, myEvent);
- updateEvt: DoUpdate(ProgWindInfo, myWindow);
- app4Evt: ShowHide(myWindow, ODD(myEvent.message));
- xCursorWithin: paramPtr^.passFlag:= TRUE;
-
- xGetPropEvt:
- myXWEventInfoPtr^.eventResult :=
- GetProperty(ProgWindInfo, myWindow,StringPtr(myXWEventInfoPtr^.eventParams[1]));
- xSetPropEvt:
- SetProperty(ProgWindInfo, myWindow,
- StringPtr(myXWEventInfoPtr^.eventParams[1]),
- Handle(myXWEventInfoPtr^.eventParams[2]));
- xCloseEvt:
- BEGIN
- KillXWindow(ProgWindInfo, myWindow);
- paramPtr^.passFlag:= TRUE;
- END;
- END; {case}
- END;
-
- PROCEDURE DoEvent;
- VAR
- savePort: GrafPtr;
- myEvent: EventRecord;
- myWindow: WindowPtr;
- myXWEventInfoPtr: XWEventInfoPtr;
-
- BEGIN
- myXWEventInfoPtr := XWEventInfoPtr(paramPtr^.params[1]);
- myWindow:= myXWEventInfoPtr^.eventWindow;
- myEvent:= myXWEventInfoPtr^.event;
-
- GetPort(savePort);
- SetPort(myWindow);
- ProcessEvent(myXWEventInfoPtr, myWindow, myEvent);
- SetPort(savePort);
- END;
-
- BEGIN {ProgressWindoid }
- WITH paramPtr^ DO
- BEGIN
-
- IF (paramCount = -1) THEN DoEvent ELSE DoSetup;
-
- END
-
- END { ProgressWindoid } ;
-
- END. { DummyUnit }
-
-
-